/**
 * Created by jianglinjie on Thu Sep 28 2017
 * @flow
 */
'use strict';
import type {
  BindPhoneParam,
  BindPhoneResult,
  UpdateUserParam,
  UpdateUserResult,
  GetUserParam,
  GetUserResult,
} from '../../types';
import { getCaptchaRedisKey } from '../../utils/CaptchaUtils';
import { isPhone, checkGender, checkAvatar, checkNickName } from '../../utils/CheckUtils';
import redis from '../../redis';
import { ErrorCode } from '../../constants';
import { CaptchaBusiness } from '../../constants';
import { createError, isMongoDuplicateKeyError } from '../../utils/ErrorUtils';
import { User } from '../../db/models';
import { logger } from '../../utils/LoggerUtils';

class UserProfileService {
  async bindPhone(param: BindPhoneParam): Promise<BindPhoneResult> {
    if (!param.uid) {
      throw createError(400, '缺少uid', ErrorCode.REQUIRE_UID);      
    }

    if (!isPhone(param.phone)) {
      throw createError(400, '手机非法', ErrorCode.PHONE_INVALID);
    }

    if (!param.captcha) {
      throw createError(400, '缺少验证码', ErrorCode.REQUIRE_CAPTCHA);
    }

    let redisKey = getCaptchaRedisKey(param.phone, CaptchaBusiness.BIND_PHONE);
    let captcha = await redis.getAsync(redisKey);
    if (captcha !== param.captcha) {
      throw createError(400, '验证码无效', ErrorCode.CAPTCHA_INVALID);
    }

    redis.delAsync(redisKey).catch(delErr => {
      logger.error('redis delete redisKey %s err', redisKey, delErr);
    });

    let doc = await User.findById(param.uid);
    if (!doc) {
      throw createError(400, '用户不存在', ErrorCode.USER_NOT_EXIST);
    }

    if (doc.phone === param.phone) {
      throw createError(400, '手机号未改变', ErrorCode.PHONE_NOT_UPDATE);        
    }

    try {
      doc.phone = param.phone;
      await doc.save();

      return {
        newPhone: doc.phone
      }
    } catch (error) {
      if (isMongoDuplicateKeyError(error)) {
        throw createError(400, '手机号已绑定', ErrorCode.PHONE_HAS_BIND);
      }

      throw error;
    }
  }

  async updateUser(param: UpdateUserParam): Promise<UpdateUserResult> {
    if (!param.uid) {
      throw createError(400, '缺少uid', ErrorCode.REQUIRE_UID);      
    }

    let update = {};

    if (param.avatar) {
      if (checkAvatar(param.avatar)) {
        update.avatar = param.avatar;
      } else {
        throw createError(400, '头像非法', ErrorCode.USER_AVATAR_INVALID);
      }
    }

    if (param.nickName) {
      if (checkNickName(param.nickName)) {
        update.nickName = param.nickName;
      } else {
        throw createError(400, '昵称非法', ErrorCode.USER_NICKNAME_INVALID);        
      }
    }

    if (param.gender) {
      if (checkGender(param.gender)) {
        update.gender = param.gender;
      } else {
        throw createError(400, '性别非法', ErrorCode.USER_GENDER_INVALID);                
      }
    }

    if (Object.keys(update).length === 0) {
      throw createError(400, '缺少参数', ErrorCode.REQUIRE_PARAMETER);
    }

    let doc = await User.findByIdAndUpdate(param.uid, update, { new: true }).exec();
    if (!doc) {
      throw createError(400, '用户不存在', ErrorCode.USER_NOT_EXIST);
    }

    return {
      uid: doc.id,
      gender: doc.gender,
      avatar: doc.avatar,
      nickName: doc.nickName,
    }
  }

  async getUser(param: GetUserParam): Promise<GetUserResult> {
    if (!param.uid) {
      throw createError(400, '缺少uid', ErrorCode.REQUIRE_UID);      
    }

    let doc = await User.findById(param.uid).exec();
    if (!doc) {
      throw createError(400, '用户不存在', ErrorCode.USER_NOT_EXIST);
    }

    return {
      uid: doc.id,
      gender: doc.gender,
      avatar: doc.avatar,
      nickName: doc.nickName,
    }
  }
}

export default new UserProfileService ();